Read Slack through its MCP server with the user's own token - #58
Merged
Conversation
The slack connection was retired because Slack's app OAuth pair returns the user's token nested under authed_user, where Gemini Enterprise never looks. Slack's MCP server advertises a separate user pair, oauth/v2_user/authorize and oauth.v2.user.access, whose response carries the user's token at the top level, so a custom agent can search and read Slack as the caller with nothing in between. slack-mcp reaches mcp.slack.com only: the token would very likely pass at the Web API too, but the connection's face is the MCP server's tools, which an mcp: block can hold to an allow list. The default scopes read; files, writing, canvases and lists are on the menu; email addresses and creating conversations are not offered at all. The retired slack entry goes: nothing may declare it, and a live successor claiming the same token prefixes would otherwise be reported as clashing with a connection no token can reach. The tests that used it as the retired example now declare one of their own. Nothing here has been taken through Gemini Enterprise yet, so the entry carries no verified date and its setup notes say what is unconfirmed. 🤖 Generated with Claude Code
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Custom agents could not read Slack with the caller's own authorization. The
slackcatalog entry was retired because Slack's app OAuth pair (oauth/v2/authorize+oauth.v2.access) returns the user's token nested underauthed_user.access_token, and Gemini Enterprise reads only the top-levelaccess_token(RFC 6749), so the token never arrived.Slack's MCP server (
https://mcp.slack.com/mcp) advertises a separate authorization server whose pair,oauth/v2_user/authorize+oauth.v2.user.access, returns the user's token at the top level. That should let Gemini Enterprise's authorization reach it with nothing in between.What
slack-mcp(src/gete/catalog/connections/slack-mcp.yaml), in the same shape asnotion-mcpandfreee-mcp.connections: [slack-mcp]plus anmcp:block pointing athttps://mcp.slack.com/mcpis all an agent needs to declare.slackentry is removed. Nothing may declare it, and a live successor claiming the same token prefixes (xoxp-,xoxe.xoxp-) would otherwise be reported as clashing with a connection no token can reach. The tests that used it as the catalog's retired example now declare a retired connection of their own; theretiredfeature itself is unchanged.slack-mcpand no longer mentions the retired entry.verified. A CLI test checks thatgete connections slack-mcpprints the setup.Design
hosts: [mcp.slack.com]only. The token is an ordinary Slack user token and the Web API would very likely take it, but the face of this connection is the MCP server's tools, which anmcp:block can hold to an allow list. Namingslack.combeside it would make every Web API method the scopes reach part of that face.token_prefixes: [xoxp-, xoxe.xoxp-]. The tokens announce themselves, so the connection is not accepted by elimination and can sit besidenotion-mcporfreee-mcp.search:read.files,files:read,chat:write,reactions:write, canvases and lists are on theoptional_scopesmenu.users:read.email, the conversation-creating*:writescopes,files:writeandemoji:readare not offered at all. Slack fixes a user token's scopes at consent, so the floor is what reading Slack takes and later additions reach nobody already authorized until their authorization is reset.scope_parameter,pkceandauthorization_queryare left unset. The user pair is reached by standard MCP clients as an RFC 8414 authorization server, which send a plainscope; S256 is supported, not required; a verbatim query would fix the scopes and the menu could not be offered beside it.examples.rejectsincludes anxoxb-bot token. The connection is per user; refusing the shape keeps it so.verified:. No authorization has been taken through Gemini Enterprise yet.Unconfirmed (stated as such in
setup:)client_secret_post, the only method the metadata names.v2_user/authorizetakes the scopes underscope;user_scopeis the switch if it answersinvalid_scope.access_type/promptparameters the authorization URL carries.resource(RFC 8707), which Gemini Enterprise does not send.refresh_token, and whether Gemini Enterprise refreshes is its own doing.Facts read off the server
Not in this PR
gete connections slack-mcp.verified:; it lands once an authorization has gone through Gemini Enterprise.slack_postandruntime/slack_post.pyare untouched.Checks
uv run pytest(875 passed),uv run ruff check .,uv run ruff format --check .,uv run mypygete connectionslistsslack-mcp;gete connections slack-mcpprints the setup notes